﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Ranet.AgOlap.Controls.General;
using Galaktika.BI.Runtime.Services;
using Galaktika.BI.Silverlight.Commands;
using System.Threading;
using Galaktika.BI.Silverlight.Services;
using Galaktika.BI.Extensibility.Dom.Dac;
using Ranet.Olap.Core.Providers.ClientServer;
using Ranet.Olap.Core;
//using Ranet.Olap.Core.Compressor;

namespace Galaktika.BI.Silverlight.Controls.General
{
    public class PivotDataLoaderEx : IPivotDataLoader
    {
        public IBindingContext Context { get; set; }
        public IBindingManager BindManager { get; set; }
        UserControl Owner = null;

        public PivotDataLoaderEx(UserControl owner)
            : base()
        {
            Owner = owner;
        }

        String DataSourceId
        {
            get
            {
                if (BindManager != null)
                {
                    return BindManager.DataManager.Name;
                }
                return String.Empty;
            }
        }

        #region IDataLoader Members

        public void LoadPivotData(object schema, object state)
        {
            PivotInitializeArgs args = XmlUtility.XmlStr2Obj<PivotInitializeArgs>(schema.ToString());
            if (args != null)
            {
                IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
                if (taskManager != null)
                {
                    InvokeSchema invokeSchema = null;
                    String taskText = String.Empty;

                    invokeSchema = CommandBuilder.CreateGetPivotDataSchema((string)this.Context.UserData["_$Id"], DataSourceId, args);
                    taskText = Localization.AppTask_DownloadingPivotData;

                    ChoiceControlInvokeSchemaWrapper wrapper = new ChoiceControlInvokeSchemaWrapper(invokeSchema, state);
                    taskManager.RunTaskAsync(
                        taskText,
                        param => this.InvokeCommand(param),
                        wrapper);
                }
            }
        }

        public void ExecuteQuery(object schema, object state)
        {
            MdxQueryArgs args = XmlUtility.XmlStr2Obj<MdxQueryArgs>(schema.ToString());
            if (args != null)
            {
                IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
                if (taskManager != null)
                {
                    InvokeSchema invokeSchema = null;
                    String taskText = String.Empty;

                    invokeSchema = CommandBuilder.CreateExecuteQuerySchema((string)this.Context.UserData["_$Id"], DataSourceId, args.Connection, args);
                    taskText = Localization.AppTask_ExecutingMDX;

                    ChoiceControlInvokeSchemaWrapper wrapper = new ChoiceControlInvokeSchemaWrapper(invokeSchema, state);
                    taskManager.RunTaskAsync(
                        taskText,
                        param => this.InvokeCommand(param),
                        wrapper);
                }
            }
        }

        public void PerformMemberAction(object schema, object state)
        {
            PerformMemberActionArgs args = XmlUtility.XmlStr2Obj<PerformMemberActionArgs>(schema.ToString());
            if (args != null)
            {
                IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
                if (taskManager != null)
                {
                    InvokeSchema invokeSchema = null;
                    String taskText = String.Empty;

                    invokeSchema = CommandBuilder.CreateDrillDownSchema((string)this.Context.UserData["_$Id"], DataSourceId, args);
                    taskText = Localization.AppTask_ExecutingDrillAction;
                    switch (args.Action)
                    { 
                        case MemberActionType.Collapse:
                            taskText = Localization.AppTask_ExecutingCollapseAction;
                            break;
                        case MemberActionType.DrillDown:
                            taskText = Localization.AppTask_ExecutingDrillDownAction;
                            break;
                        case MemberActionType.Expand:
                            taskText = Localization.AppTask_ExecutingExpandAction;
                            break;
                    }

                    ChoiceControlInvokeSchemaWrapper wrapper = new ChoiceControlInvokeSchemaWrapper(invokeSchema, state);
                    taskManager.RunTaskAsync(
                        taskText,
                        param => this.InvokeCommand(param),
                        wrapper);
                }
            }
        }

        public void PerformServiceCommand(object schema, object state)
        {
            ServiceCommandArgs args = XmlUtility.XmlStr2Obj<ServiceCommandArgs>(schema.ToString());
            if (args != null)
            {
                IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
                if (taskManager != null)
                {
                    InvokeSchema invokeSchema = null;
                    String taskText = String.Empty;

                    invokeSchema = CommandBuilder.CreateRunServiceCommandSchema((string)this.Context.UserData["_$Id"], DataSourceId, args);
                    taskText = String.Empty;

                    ServiceCommandType actionType = args.Command;
                    switch (actionType)
                    {
                        case ServiceCommandType.Back:
                        case ServiceCommandType.Forward:
                            taskText = String.Format(Localization.AppTask_ExecutingNavigationCommand, actionType.ToString());
                            break;
                        default:
                            taskText = String.Format(Localization.AppTask_ExecutingServiceCommand, actionType.ToString());
                            break;
                    }

                    ChoiceControlInvokeSchemaWrapper wrapper = new ChoiceControlInvokeSchemaWrapper(invokeSchema, state);
                    taskManager.RunTaskAsync(
                        taskText,
                        param => this.InvokeCommand(param),
                        wrapper);
                }
            }
        }

        public void GetToolBarInfo(object schema, object state)
        {
            InvokeSchema invokeSchema = null;
            String taskText = String.Empty;

            invokeSchema = CommandBuilder.CreateToolBarInfoSchema((string)this.Context.UserData["_$Id"], DataSourceId);

            ChoiceControlInvokeSchemaWrapper wrapper = new ChoiceControlInvokeSchemaWrapper(invokeSchema, state);
            this.InvokeCommand(wrapper);
        }

        public void UpdateCube(object schema, object state)
        {
            UpdateCubeArgs args = XmlUtility.XmlStr2Obj<UpdateCubeArgs>(schema.ToString());
            if (args != null)
            {
                IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
                if (taskManager != null)
                {
                    InvokeSchema invokeSchema = null;
                    String taskText = String.Empty;

                    var exe = (IExecutionContext)this.Context.Services.GetService(typeof(IExecutionContext));
                    if (exe != null)
                    {
                        var conn = exe.GetNamedObject(this.Context, this.DataSourceId) as BrickDataSource;
                        if (conn != null)
                        {
                            args.ConnectionString = exe.Parse(this.Context, conn.Connection.ConnectionString);
                        }
                    }

                    invokeSchema = CommandBuilder.CreateUpdateCubeSchema(
                        (string)this.Context.UserData["_$Id"], 
                        DataSourceId, 
                        args, 
                        this.GetSessionId(args.ConnectionString));
                    taskText = Localization.AppTask_ExecutingUpdateCubeCommand;

                    ChoiceControlInvokeSchemaWrapper wrapper = new ChoiceControlInvokeSchemaWrapper(invokeSchema, state);
                    taskManager.RunTaskAsync(
                        taskText,
                        param => this.InvokeCommand(param),
                        wrapper);
                }
            }
        }

        private string GetSessionId(string connectionString)
        {
            var sessionProvider = (IAdomdSessionProvider)this.Context.Services.GetService(typeof(IAdomdSessionProvider));
            if (sessionProvider != null)
            {
                return sessionProvider.GetSessionId(connectionString);
            }

            return null;
        }

        void InvokeCommand(object state)
        {
            ChoiceControlInvokeSchemaWrapper wrapper = state as ChoiceControlInvokeSchemaWrapper;
            if (wrapper != null)
            {
                InvokeSchema schema = wrapper.Schema;
                using (var cmd = CommandDispatcher.Dispatch(schema))
                {
                    InvokeResultSchema res = cmd.Invoke();

                    String content = res.Content;
#warning Отключена zip-архивация
                    //if (res.IsArchive)
                    //{
                    //    content = ZipCompressor.DecompressFromBase64String(res.Content);
                    //}

                    InvokeResultDescriptor result = new InvokeResultDescriptor(content);
                    if (res.ContentType == KnownContentTypes.ADOMDError || 
                        res.ContentType == KnownContentTypes.Error)
                        result.ContentType = InvokeContentType.Error;

                    if (res.ContentType == KnownContentTypes.ADOMDError)
                    {
                        var output = (IOutputService)this.Context.Services.GetService(typeof(IOutputService));
                        if (output != null && Owner != null)
                        {
                            Owner.Dispatcher.BeginInvoke(() => output.ShowWarning(result.Content));
                        }
                    }

                    Raise_DataLoaded(new DataLoaderEventArgs(result, null, wrapper.UserState));
                }
            }
        }

        void Raise_DataLoaded(DataLoaderEventArgs args)
        {
            EventHandler<DataLoaderEventArgs> handler = this.DataLoaded;

            if (handler != null)
            {
                if (Owner != null)
                {
                    Owner.Dispatcher.BeginInvoke(delegate { handler(this, args); });
                }
                else
                {
                    handler(this, args);
                }
            }
        }

        #endregion

        #region IDataLoader Members

        public event EventHandler<DataLoaderEventArgs> DataLoaded;

        #endregion

        #region IPivotDataLoader Members

        public void ChangeDataSource(object schema, object state)
        {
            PivotInitializeArgs args = XmlUtility.XmlStr2Obj<PivotInitializeArgs>(schema.ToString());
            if (args != null)
            {
                IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
                if (taskManager != null)
                {
                    InvokeSchema invokeSchema = null;
                    String taskText = String.Empty;

                    invokeSchema = CommandBuilder.CreateChangeDataSourceSchema((string)this.Context.UserData["_$Id"], DataSourceId, args);
                    taskText = Localization.AppTask_DownloadingPivotData;

                    ChoiceControlInvokeSchemaWrapper wrapper = new ChoiceControlInvokeSchemaWrapper(invokeSchema, state);
                    //taskManager.ProcessTaskItem(taskText,
                    //    new WaitCallback(param =>
                    //    { ThreadPool.QueueUserWorkItem(new WaitCallback(InvokeCommand), param); }
                    //    ), wrapper);
                    taskManager.RunTaskAsync(
                        taskText,
                        param => this.InvokeCommand(param),
                        wrapper);
                }
            }
        }

        #endregion
    }
}
